package me.zhengjie.minbearwcs.serivce.mission.processor.rework;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.minbearwcs.dao.mission.inf.WcsMissionDao;
import me.zhengjie.minbearwcs.dao.rework.inf.ReworkOrderDetailDao;
import me.zhengjie.minbearwcs.dao.rework.inf.ReworkTaskRecordDao;
import me.zhengjie.minbearwcs.dao.rework.inf.ReworkTaskRecordHistoryDao;
import me.zhengjie.minbearwcs.dao.stock.inf.PalletDao;
import me.zhengjie.minbearwcs.dao.storage.inf.SmallStorageDao;
import me.zhengjie.minbearwcs.entity.DTO.agv.common.PointAndPass;
import me.zhengjie.minbearwcs.entity.DTO.agv.task.AgvActionSource;
import me.zhengjie.minbearwcs.entity.DTO.agv.task.AgvTaskSource;
import me.zhengjie.minbearwcs.entity.DTO.agv.task.actionEnum.AgvAction;
import me.zhengjie.minbearwcs.entity.DTO.transfer.Tuple;
import me.zhengjie.minbearwcs.entity.PO.agv.missionEnum.AgvMissionType;
import me.zhengjie.minbearwcs.entity.PO.wcs.mission.WcsMission;
import me.zhengjie.minbearwcs.entity.PO.wcs.mission.status.ReworkShiftingMissionStatus;
import me.zhengjie.minbearwcs.entity.PO.wcs.mission.type.MissionType;
import me.zhengjie.minbearwcs.entity.PO.wcs.rework.ReworkTaskRecord;
import me.zhengjie.minbearwcs.entity.PO.wcs.rework.history.ReworkTaskRecordHistory;
import me.zhengjie.minbearwcs.entity.PO.wcs.rework.status.ReworkTaskRecordStatus;
import me.zhengjie.minbearwcs.entity.PO.wcs.storage.SmallStorage;
import me.zhengjie.minbearwcs.resource.WcsResource;
import me.zhengjie.minbearwcs.serivce.agv.task.agvTask.AgvTaskDispatcher;
import me.zhengjie.minbearwcs.serivce.mission.processor.MissionProcessor;
import me.zhengjie.minbearwcs.serivce.mission.processor.MissionProcessorCommonUtil;
import me.zhengjie.minbearwcs.serivce.mission.storageProcessor.locker.Floor2.Storage2FloorLocker;
import me.zhengjie.minbearwcs.serivce.mission.storageProcessor.locker.Floor5Or6.InboundStorage5Or6FloorLocker;
import me.zhengjie.minbearwcs.serivce.mission.storageProcessor.locker.Floor5Or6.Storage5Or6FloorPassSelector;
import me.zhengjie.minbearwcs.utils.IdWorker;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;

@Slf4j
@Component
@RequiredArgsConstructor
public class ReworkShiftingMissionProcessor implements MissionProcessor {

    private final ReworkTaskRecordDao reworkTaskRecordDao;
    private final ReworkTaskRecordHistoryDao reworkTaskRecordHistoryDao;
    private final AgvTaskDispatcher getPutTaskDispatcher;
    private final TransactionTemplate transactionTemplate;
    private final WcsMissionDao wcsMissionDao;
    private final WcsResource wcsResource;
    private final IdWorker idWorker;
    private final MissionProcessorCommonUtil commonUtil;
    private final SmallStorageDao smallStorageDao;
    private final ReworkOrderDetailDao reworkOrderDetailDao;
    private final PalletDao palletDao;
    private final Storage2FloorLocker storage2FloorLocker;
    private final InboundStorage5Or6FloorLocker inboundStorage5Or6FloorLocker;
    private final Storage5Or6FloorPassSelector storage5Or6FloorPassSelector;


    private final Object lock = new Object();

    @Override
    public MissionType getMissionType() {
        return MissionType.REWORK_SHIFTING;
    }

    @Override
    public void process(WcsMission missionInfo) {
        ReworkShiftingMissionStatus missionStatus = (ReworkShiftingMissionStatus) missionInfo.getEnumMissionStatus();

        switch (missionStatus) {
            case WAIT_FOR_DISPATCH:
                dispatchAgvTask(missionInfo);
                break;
            case DISPATCHING:
                break;
            case PROCESSING:
                monitorMission(missionInfo);
                break;
            case FINISH:
                finishWcsMission(missionInfo);
                break;
            case CANCEL:
                break;
        }
    }


    public ReworkTaskRecord getTaskRecord(String detailId) {
        return reworkTaskRecordDao.selectByRecordId(detailId);
    }


    public boolean statusChangeDISPATCHING(Integer missionId) {
        if (ReworkShiftingMissionStatus.WAIT_FOR_DISPATCH == wcsMissionDao.selectMissionStatusById(missionId)) {
            synchronized (lock) {
                if (ReworkShiftingMissionStatus.WAIT_FOR_DISPATCH == wcsMissionDao.selectMissionStatusById(missionId)) {
                    return Boolean.TRUE.equals(transactionTemplate.execute(status -> {
                        try {
                            wcsMissionDao.updateMissionStatusById(missionId, ReworkShiftingMissionStatus.DISPATCHING.name());
                            return true;
                        } catch (Exception e) {
                            log.error("wcs任务状态转换出错", e);
                            status.setRollbackOnly();
                        }
                        return false;
                    }));
                }
            }
        }

        return false;
    }


    public void dispatchAgvTask(WcsMission missionInfo) {
        if (!statusChangeDISPATCHING(missionInfo.getId())) return;

        ReworkTaskRecord taskRecord = getTaskRecord(missionInfo.getAssociatedDetailId());


        wcsResource.getExecutor().execute(() -> {
            Boolean executeRes = transactionTemplate.execute(status -> {
                try {
                    if(taskRecord.getWaitSmallStorage() != null){
                        SmallStorage smallStorage = smallStorageDao.selectBySmallStorage(taskRecord.getWaitSmallStorage());
                        if (smallStorage.getPalletCode() != null) return false;
                    }

                    Tuple<String> start = storage5Or6FloorPassSelector.selectPass(taskRecord.getStartPoint());
                    // 借用
                    Tuple<PointAndPass> lockAmend = inboundStorage5Or6FloorLocker.lockAmend(taskRecord.getEndPoint());
                    reworkTaskRecordDao.updateEndPointByRecordId(taskRecord.getReworkTaskRecordId(), lockAmend.value.getPointStorage());

                    String agvTaskId = "Task_Agv_" + idWorker.nextId();
                    AgvTaskSource agvTaskSource = new AgvTaskSource(agvTaskId, AgvMissionType.INBOUND_TYPE, 1, missionInfo.getMissionId(), missionInfo.getMissionType(),
                            ReworkShiftingMissionStatus.PROCESSING.name(), taskRecord.getPalletCode(),start.value,lockAmend.value.getPassStorage());
                    agvTaskSource.addAction(new AgvActionSource(taskRecord.getStartPoint(), AgvAction.GET))
                            .addAction(new AgvActionSource(lockAmend.value.getPointStorage(), AgvAction.PUT));


                    if (getPutTaskDispatcher.dispatch(agvTaskSource)) {
                        wcsMissionDao.updateMissionStatusById(missionInfo.getId(), ReworkShiftingMissionStatus.PROCESSING.name());
                    } else {
                        wcsMissionDao.updateMissionStatusById(missionInfo.getId(), ReworkShiftingMissionStatus.WAIT_FOR_DISPATCH.name());
                    }
                    return true;
                } catch (Exception e) {
                    log.error("wcs任务：{}，生成agv任务失败", missionInfo.getMissionId(), e);
                    status.setRollbackOnly();
                }
                return false;
            });

            if (Boolean.FALSE.equals(executeRes)) {
                wcsMissionDao.updateMissionStatusById(missionInfo.getId(), ReworkShiftingMissionStatus.WAIT_FOR_DISPATCH.name());
            }

        });
    }


    public void monitorMission(WcsMission missionInfo) {

    }

    public void finishWcsMission(WcsMission missionInfo) {
        transactionTemplate.executeWithoutResult(status -> {
            try {
                missionInfo.setFinishTime(LocalDateTime.now());
                commonUtil.transformMissionHistory(missionInfo);

                ReworkTaskRecord taskRecord = getTaskRecord(missionInfo.getAssociatedDetailId());
                taskRecord.setStatus(ReworkTaskRecordStatus.COMPLETE);
                taskRecord.setFinishTime(LocalDateTime.now());
                reworkTaskRecordHistoryDao.insert(
                        new ReworkTaskRecordHistory(null, taskRecord.getReworkTaskRecordId(), taskRecord.getReworkOrderCode(),
                                taskRecord.getReworkOrderDetailCode(), taskRecord.getPalletCode(),
                                taskRecord.getStatus(), taskRecord.getStartPoint(), taskRecord.getEndPoint(),
                                taskRecord.getMissioonType(), taskRecord.getWaitSmallStorage(),
                                taskRecord.getStartTime(), taskRecord.getFinishTime())
                );
                reworkTaskRecordDao.deleteById(taskRecord.getId());

            } catch (Exception e) {
                log.error("任务结束错误", e);
                status.setRollbackOnly();
            }
        });

    }


}
